<!-- 角色授权菜单抽屉 -->
<!-- created by lx 2023/3/22 -->
<!--created by yuyupeng 2023/4/19-->
<template>
  <div>
    <!-- 按钮 -->
    <a-link @click="openDrawer">菜单授权</a-link>

    <!-- 抽屉：菜单授权 -->
    <a-drawer
      :visible="visible"
      title="菜单授权"
      :width="360"
      @ok="authorizeRole"
      @cancel="closeDrawer"
    >
      <a-spin :loading="loading">
        <a-tree
          :checked-keys="checkedNodeKeys"
          :data="treeData"
          checkable
          :field-names="{
            key: 'id',
            title: 'name',
            children: 'children',
            icon: 'checkable',
          }"
          @check="onCheck"
        />
      </a-spin>
    </a-drawer>
  </div>
</template>

<script lang="ts" setup>
  import { ref, watch, computed } from 'vue';
  import { TreeNodeData, Message } from '@arco-design/web-vue';
  import { queryMenuRecordTree } from '@/api/system/menu';
  import { queryRoleAuthList, updateRoleAuth } from '@/api/system/permission';

  const props = defineProps({
    roleId: {
      type: String,
      required: true,
    },
  });

  const visible = ref<boolean>(false);
  const openDrawer = () => {
    checkedNodeKeys.value = [];
    halfCheckedNodeKeys.value = [];
    getMenuTree();
    getAuthList();
    visible.value = true;
  };
  const closeDrawer = () => {
    visible.value = false;
  };

  const loadingMenu = ref<boolean>(false);
  const loadingAuth = ref<boolean>(false);

  const treeData = ref<TreeNodeData[]>([]);
  const authList = ref<string[]>([]);
  const checkedNodeKeys = ref<string[]>([]);
  const halfCheckedNodeKeys = ref<string[]>([]);
  const onCheck = (
    checkedKeys: (string | number)[],
    { halfCheckedKeys }: { halfCheckedKeys: (string | number)[] }
  ) => {
    checkedNodeKeys.value = [...(checkedKeys as string[])];
    halfCheckedNodeKeys.value = [...halfCheckedKeys] as string[];
  };
  const getMenuTree = async () => {
    loadingMenu.value = true;
    try {
      const { data } = await queryMenuRecordTree();
      treeData.value = data;
    } finally {
      loadingMenu.value = false;
    }
  };
  const getAuthList = async () => {
    loadingAuth.value = true;
    try {
      const { data } = await queryRoleAuthList(props.roleId);
      authList.value = data;
    } finally {
      loadingAuth.value = false;
    }
  };

  // 遍历以tree为根节点的菜单树
  // 根据list确定权限节点决定勾选并筛去半勾选节点
  const traverseCheckAuth = (tree: any, list: string[]): number => {
    let result = 0;
    if (list.findIndex((e) => e === tree.id) > -1) {
      result = 1;
    }
    if (tree.children && tree.children.length > 0) {
      tree.children.forEach((n: any) => {
        // 筛去半勾选节点
        result = traverseCheckAuth(n, list) && result;
      });
    }
    if (result) {
      checkedNodeKeys.value = [...checkedNodeKeys.value, tree.id];
    }
    return result;
  };

  // 根据权限列表为菜单树构建权限树
  const buildAuthTree = () => {
    checkedNodeKeys.value = [];
    treeData.value.forEach((node) => {
      traverseCheckAuth(node, authList.value);
    });
  };

  const loading = computed(() => {
    return loadingMenu.value || loadingAuth.value;
  });

  watch(loading, (value) => {
    if (!value) {
      buildAuthTree();
    }
  });

  // func：保存菜单权限信息
  const authorizeRole = async () => {
    try {
      await updateRoleAuth({
        roleId: props.roleId,
        menuIds: [...checkedNodeKeys.value, ...halfCheckedNodeKeys.value],
      });
      Message.success('修改成功');
    } finally {
      closeDrawer();
    }
  };
</script>
